﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using ZYSocket.Server;
using ZYSocket.share;
using System.Net.Sockets;
using System.Configuration;
using FX.CC.Andon.EqKanban.KanbanDataSvcRef;
using System.IO;
using System.Text;

namespace FX.CC.Andon.EqKanban
{
    static class Program
    {
        static frmTaskList taskListForm;
        static frmPrdTaskInfo prdTaskInfoForm;
        static frmAndon andonDispForm;
        static frmViewDoc viewDocForm;
        static frmModelInfo modelInfoForm;
        static frmManualViewDoc manualDocForm;

        static ZYSocketSuper server;

        static Action<PrdTaskInfoWrapper> actUpdateTaskInfoUI;
        static Action<DocWrapper> actShowDocForm;
        static Action<string, IList<int>> actShowManualDocForm;
        static Action actManualDocPrevious;
        static Action actManualDocNext;
        static Action actManualDocClose;
        static Action<AndonDispWrapper, AndonReportType> actUpdateAndonDispUI;
        static Action actUpdateAndonReduceMin;
        static Action actCloseTaskInfoForm;
        static Action<ModelInfoWrapper> actActiveModelForm;
        static Action actCloseModelForm;

        public static EquipmentEntity bindingEq;

        public static bool cursorShown = false;

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            bool testOK = false;
            using (var frm = new frmConnectionTest())
            {
                testOK = frm.ShowDialog() == DialogResult.OK;
            }
            if (!testOK) return;

#if !DEBUG
            bool flag = _Upgrade.Upgrade(2);
            if (flag)
            {
                string upgradeToolLocation = Application.StartupPath + "\\FX.CC.Andon.UpgradeTool.EXE";
                System.Diagnostics.Process.Start(upgradeToolLocation, "\"" + Application.ExecutablePath + "\"");
                return;
            }
#endif

            try
            {
                var svrTime = new KanbanDataSvc().GetServerTime();
                _API.SetLocalTime(svrTime);
            }
            catch { }

            Cursor.Hide();

            string docDir = Application.StartupPath + "\\Doc";
            if (!Directory.Exists(docDir)) {
                Directory.CreateDirectory(docDir);
            }

            string eqCode = ConfigurationManager.AppSettings["EqCode"];
            try
            {
                bindingEq = new KanbanDataSvc().GetEquipmentByCode(eqCode);
            }
            catch {
                bindingEq = new EquipmentEntity();
            }

            actUpdateTaskInfoUI = new Action<PrdTaskInfoWrapper>(obj =>
            {
                if (prdTaskInfoForm == null || prdTaskInfoForm.IsDisposed)
                {
                    prdTaskInfoForm = new frmPrdTaskInfo();
                    prdTaskInfoForm.WindowState = FormWindowState.Maximized;
                    prdTaskInfoForm.Show();
                }
                else
                {
                    //prdTaskInfoForm.Activate();
                }

                prdTaskInfoForm.SetContent(obj);
            });

            actShowDocForm = new Action<DocWrapper>(obj =>
            {
                if (viewDocForm == null || viewDocForm.IsDisposed)
                {
                    viewDocForm = new frmViewDoc(obj);
                    viewDocForm.WindowState = FormWindowState.Maximized;
                    viewDocForm.Show();
                }
                else
                {
                    viewDocForm.Activate();
                }
            });

            actShowManualDocForm = new Action<string, IList<int>>((path, pageSet) =>
            {
                if (manualDocForm == null || manualDocForm.IsDisposed)
                {
                    manualDocForm = new frmManualViewDoc();
                    manualDocForm.WindowState = FormWindowState.Maximized;
                    manualDocForm.Show();
                }
                else
                {
                    manualDocForm.Activate();
                }
                manualDocForm.SetPdfFileName(path, pageSet);
            });

            actManualDocPrevious = new Action(() => {
                try {
                    if (manualDocForm == null || manualDocForm.IsDisposed)
                    {
                        return;
                    }
                    manualDocForm.Activate();
                    manualDocForm.ShowPreviousPage();
                }
                catch { }
            });

            actManualDocNext = new Action(() => {
                try
                {
                    if (manualDocForm == null || manualDocForm.IsDisposed)
                    {
                        return;
                    }
                    manualDocForm.Activate();
                    manualDocForm.ShowNextPage();
                }
                catch { }
            });

            actManualDocClose = new Action(() => {
                if (manualDocForm == null || manualDocForm.IsDisposed)
                {
                    return;
                }
                manualDocForm.CloseForm();
            });

            actUpdateAndonDispUI = new Action<AndonDispWrapper, AndonReportType>((obj, reportType) =>
            {
                if (andonDispForm == null || andonDispForm.IsDisposed)
                {
                    andonDispForm = new frmAndon();
                    andonDispForm.WindowState = FormWindowState.Maximized;
                    andonDispForm.Show();
                }
                else
                {
                    andonDispForm.Activate();
                }

                switch (reportType)
                {
                    case AndonReportType.ReportError:
                        andonDispForm.ReportError(obj);
                        break;

                    case AndonReportType.ReportSign:
                        andonDispForm.ReportSign(obj);
                        break;

                    case AndonReportType.ReportClear:
                        andonDispForm.ReportClear(obj);
                        break;
                }
            });

            actUpdateAndonReduceMin = new Action(() => {
                if (andonDispForm == null || andonDispForm.IsDisposed) {
                    return;
                }

                andonDispForm.SetReduceTime();
            });

            actCloseTaskInfoForm = new Action(() =>
            {
                try
                {
                    prdTaskInfoForm.Close();
                }
                catch{}
            });

            actActiveModelForm = new Action<ModelInfoWrapper>((obj) =>
            {
                if (modelInfoForm == null || modelInfoForm.IsDisposed)
                {
                    modelInfoForm = new frmModelInfo();
                    modelInfoForm.WindowState = FormWindowState.Maximized;
                    modelInfoForm.Show();
                }
                else
                {
                    modelInfoForm.Activate();
                }
                modelInfoForm.SetContent(obj);
            });

            actCloseModelForm = new Action(() =>
            {
                try
                {
                    modelInfoForm.Close();
                }
                catch { }
            });

            InitSocketSvr();
            taskListForm = new frmTaskList();
            taskListForm.WindowState = FormWindowState.Maximized;
            Application.Run(taskListForm);
        }

        static void InitSocketSvr()
        {
            server = new ZYSocketSuper();
            server.BinaryInput = new BinaryInputHandler(BinaryGot); //设置输入代理
            server.Connetions = new ConnectionFilter(ClientConnected); //设置连接代理
            server.MessageInput = new MessageInputHandler(ClientDisconnected); //设置 客户端断开
            server.Start(); //启动服务器
        }

        /// <summary>
        /// 用户断开代理（你可以根据socketAsync 读取到断开的
        /// </summary>
        /// <param name="message">断开消息</param>
        /// <param name="socketAsync">断开的SOCKET</param>
        /// <param name="erorr">错误的ID</param>
        static void ClientDisconnected(string message, SocketAsyncEventArgs socketAsync, int erorr)
        {
            Console.WriteLine(message);
            socketAsync.UserToken = null;
            socketAsync.AcceptSocket.Close();
        }
        /// <summary>
        /// 用户连接的代理
        /// </summary>
        /// <param name="socketAsync">连接的SOCKET</param>
        /// <returns>如果返回FALSE 则断开连接,这里注意下 可以用来封IP</returns>
        static bool ClientConnected(SocketAsyncEventArgs socketAsync)
        {
            Console.WriteLine("UserConn {0}", socketAsync.AcceptSocket.RemoteEndPoint.ToString());
            socketAsync.UserToken = null;
            return true;
        }

        /// <summary>
        /// 数据包输入
        /// </summary>
        /// <param name="data">输入数据</param>
        /// <param name="socketAsync">该数据包的通讯SOCKET</param>
        static void BinaryGot(byte[] data, SocketAsyncEventArgs socketAsync)
        {
            if (socketAsync.UserToken == null) //如果此SOCKET绑定的对象为NULL
            {
                //注意这里为了 简单 所以就绑定了个 ZYNetBufferReadStreamV2 类，本来这里应该绑定用户类对象，
                //并在用户类里面建立 初始化 一个 ZYNetBufferReadStreamV2 类，这样就能通过用户类保存更多的信息了。
                //比如用户名，权限等等
                socketAsync.UserToken = new ZYNetBufferReadStream(1024);
            }

            ZYNetBufferReadStream stream = socketAsync.UserToken as ZYNetBufferReadStream; //最新的数据包整合类
            stream.Write(data);

            StringBuilder sb = new StringBuilder();
            foreach (var i in data)
            {
                sb.Append(i.ToString("X"));
                sb.Append(" ");
            }
            System.Diagnostics.Debug.WriteLine(sb.ToString());

            byte[] datax;
            while (stream.Read(out datax))
            {
                PkgGot(datax, socketAsync);
            }
        }

        static void PkgGot(byte[] data, SocketAsyncEventArgs e)
        {
            try
            {
                //建立一个读取数据包的类 参数是数据包
                //这个类的功能很强大,可以读取数据包的数据,并可以把你发送过来的对象数据,转换对象引用
                ReadBytes read = new ReadBytes(data);

                int lengt; //数据包长度,用于验证数据包的完整性
                int cmd; //数据包命令类型

                //注意这里一定要这样子写,这样子可以保证所有你要度的数据是完整的,如果读不出来 Raed方法会返回FALSE,从而避免了错误的数据导致崩溃
                if (read.ReadInt32(out lengt) && read.Length == lengt && read.ReadInt32(out cmd))
                {  //read.Read系列函数是不会产生异常的
                    PkgType pkgType = (PkgType)cmd;
                    //根据命令读取数据包
                    switch (pkgType)
                    {
                        //pkgID(string), eqCode(string), PrdName(string), planQty(decimal), realQty(decimal), rate(string)
                        case PkgType.TaskStart:
                            {
                                string pkgID, eqCode, prdCode;
                                float rate;
                                int planQty, realQty;
                                long planStartTick, planEndTick, startTimeTick;

                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out prdCode)
                                    && read.ReadInt32(out planQty) && read.ReadInt32(out realQty) && read.ReadFloat(out rate)
                                    && read.ReadInt64(out planStartTick) && read.ReadInt64(out planEndTick) && read.ReadInt64(out startTimeTick))
                                {
                                    PrdTaskInfoWrapper taskObj = new PrdTaskInfoWrapper();
                                    taskObj.PrdCode = prdCode;
                                    taskObj.Rate = rate;
                                    taskObj.PlanQty = planQty;
                                    taskObj.RealQty = realQty;

                                    if (planStartTick != -1)
                                    {
                                        taskObj.PlanStartTime = new DateTime(planStartTick);
                                    }

                                    if (planEndTick != -1)
                                    {
                                        taskObj.PlanEndTime = new DateTime(planEndTick);
                                    }

                                    if (startTimeTick != -1)
                                    {
                                        taskObj.StartTime = new DateTime(startTimeTick);
                                    }

                                    taskListForm.BeginInvoke(actUpdateTaskInfoUI, taskObj);
                                }
                            }
                            break;

                        case PkgType.ShowDoc:
                            {
                                //pkgID(string), eqCode(string), OpFile(string), OpDispPages, CheckFile, ChkDispPages
                                string pkgID, eqCode, opFile, opDispPages, checkFile, chkDispPages;

                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out opFile)
                                    && read.ReadString(out opDispPages) && read.ReadString(out checkFile) && read.ReadString(out chkDispPages))
                                {
                                    if (string.IsNullOrEmpty(opDispPages) && string.IsNullOrEmpty(chkDispPages))
                                    {
                                        return;
                                    }
                                    DocWrapper docObj = new DocWrapper();
                                    docObj.OpFile = opFile;
                                    docObj.OpDispPages = opDispPages;
                                    docObj.CheckFile = checkFile;
                                    docObj.ChkDispPages = chkDispPages;

                                    taskListForm.BeginInvoke(actShowDocForm, docObj);
                                }
                            }
                            break;

                        case PkgType.TaskEnd:
                            {
                                //pkgID(string), eqCode(string), taskID(string)
                                string pkgID, eqCode, taskID;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out taskID))
                                {
                                    taskListForm.BeginInvoke(actCloseTaskInfoForm);
                                }
                            }
                            break;

                        case PkgType.ErrorFire:
                            {
                                //server.SendData(e.AcceptSocket, data);
                                /*
                                 * public string EventID { get; set; }

                                    public string ETypeName { get; set; }

                                    public string DetailName { get; set; }

                                    public DateTime StartTime { get; set; }

                                    public string OpUserName { get; set; }

                                    public string OpMobileNo { get; set; }
                                 */
                                string pkgID, eqCode, eventID, eTypeName, detailName, startTimeStr, opName, OpMob;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out eventID)
                                    && read.ReadString(out eTypeName) && read.ReadString(out detailName) && read.ReadString(out startTimeStr)
                                    && read.ReadString(out opName) && read.ReadString(out OpMob))
                                {
                                    AndonDispWrapper dispObj = new AndonDispWrapper();
                                    dispObj.EventID = eventID;
                                    dispObj.ETypeName = eTypeName;
                                    dispObj.DetailName = detailName;
                                    dispObj.StartTime = Convert.ToDateTime(startTimeStr);
                                    dispObj.OpUserName = opName;
                                    dispObj.OpMobileNo = OpMob;

                                    taskListForm.BeginInvoke(actUpdateAndonDispUI, dispObj, AndonReportType.ReportError);
                                }
                            }
                            break;

                        case PkgType.ErrorSign:
                            {
                                //server.SendData(e.AcceptSocket, data);
                                /*
                                 *  eventID, signuser,  rspTime
                                 */
                                string pkgID, eqCode, eventID, signUser;
                                double rspTime;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out eventID)
                                    && read.ReadString(out signUser) && read.ReadDouble(out rspTime))
                                {
                                    AndonDispWrapper dispObj = new AndonDispWrapper();
                                    dispObj.EventID = eventID;
                                    dispObj.SignUserName = signUser;
                                    dispObj.RspTime = rspTime;

                                    taskListForm.BeginInvoke(actUpdateAndonDispUI, dispObj, AndonReportType.ReportSign);
                                }
                            }
                            break;

                        case PkgType.ErrorClear:
                            {
                                //server.SendData(e.AcceptSocket, data);
                                /*
                                 *  eventID, signuser,  rspTime
                                 */
                                string pkgID, eqCode, eventID;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out eventID))
                                {
                                    AndonDispWrapper dispObj = new AndonDispWrapper();
                                    dispObj.EventID = eventID;

                                    taskListForm.BeginInvoke(actUpdateAndonDispUI, dispObj, AndonReportType.ReportClear);
                                }
                            }
                            break;

                        case PkgType.ModelStart:
                            {
                                //server.SendData(e.AcceptSocket, data);
                                /*
                                 *  eventID, signuser,  rspTime
                                 */
                                string pkgID, eqCode, startTimeStr;
                                float modelMin;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out startTimeStr) && read.ReadFloat(out modelMin))
                                {
                                    ModelInfoWrapper modelInfoObj = new ModelInfoWrapper();
                                    modelInfoObj.ModelMin = modelMin;
                                    modelInfoObj.StartTime = Convert.ToDateTime(startTimeStr);
                                    taskListForm.BeginInvoke(actActiveModelForm, modelInfoObj);
                                }
                            }
                            break;

                        case PkgType.ModelEnd:
                            {
                                string pkgID, eqCode;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode))
                                {
                                    taskListForm.BeginInvoke(actCloseModelForm);
                                }
                            }
                            break;

                        case PkgType.ManualShowDoc:
                            {
                                string pkgID, eqCode, path, pageSetStr;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode) && read.ReadString(out path) && read.ReadString(out pageSetStr))
                                {
                                    string[] pages = pageSetStr.Split(';');
                                    var pageSet = pages.Select(p=>Convert.ToInt32(p)).ToList();
                                    taskListForm.BeginInvoke(actShowManualDocForm, path, pageSet);
                                }
                            }
                            break;

                        case PkgType.PreviousPage:
                            {
                                string pkgID, eqCode;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode))
                                {
                                    taskListForm.BeginInvoke(actManualDocPrevious);
                                }
                            }
                            break;

                        case PkgType.NextPage:
                            {
                                string pkgID, eqCode;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode))
                                {
                                    taskListForm.BeginInvoke(actManualDocNext);
                                }
                            }
                            break;

                        case PkgType.CloseDoc:
                            {
                                string pkgID, eqCode;
                                if (read.ReadString(out pkgID) && read.ReadString(out eqCode))
                                {
                                    taskListForm.BeginInvoke(actManualDocClose);
                                }
                            }
                            break;

                        case PkgType.KbResume:
                            {
                                taskListForm.BeginInvoke(new Action(() =>
                                {
                                    try
                                    {
                                        if (prdTaskInfoForm != null)
                                        {
                                            if (!prdTaskInfoForm.IsDisposed)
                                            {
                                                prdTaskInfoForm.Close();
                                            }
                                        }

                                        if (andonDispForm != null)
                                        {
                                            if (!andonDispForm.IsDisposed)
                                            {
                                                andonDispForm.Close();
                                            }
                                        }

                                        if (modelInfoForm != null)
                                        {
                                            if (!modelInfoForm.IsDisposed)
                                            {
                                                modelInfoForm.Close();
                                            }
                                        }

                                        if (manualDocForm != null)
                                        {
                                            if (!manualDocForm.IsDisposed)
                                            {
                                                manualDocForm.Close();
                                            }
                                        }
                                    }
                                    catch { }
                                }));
                            }
                            break;

                        case PkgType.ReportReduceMin:
                            {
                                taskListForm.BeginInvoke(actUpdateAndonReduceMin);
                            }
                            break;

                        case PkgType.GetNewOpDoc:
                        case PkgType.GetNewCheckDoc:
                            {
                                //taskListForm.BeginInvoke(actUpdateAndonReduceMin);
                                string pkgID;
                                string relatedFileUrl;
                                if (read.ReadString(out pkgID) && read.ReadString(out relatedFileUrl))
                                {
                                    string webBasePath = ConfigurationManager.AppSettings["WebBasePath"];
                                    //taskListForm.BeginInvoke(actManualDocClose);
                                    relatedFileUrl = relatedFileUrl.StartsWith("/") ? relatedFileUrl : ("/" + relatedFileUrl);
                                    string opFileUrl = webBasePath + relatedFileUrl;

                                    string targetFile = Application.StartupPath + "\\Doc\\" + relatedFileUrl.Split('/').Last();
                                    try
                                    {
                                        HttpFile.Download(opFileUrl, targetFile);

                                        taskListForm.BeginInvoke(new Action(()=>new frmDownloadedTips().Show()));
                                    }
                                    catch { }
                                }
                            }
                            break;
                    }
                }
            }
            catch (Exception er)
            {
                Console.WriteLine(er.ToString());
            }
        }
    }

    public static class _MsgBox
    {
        public static DialogResult PopInfo(string content)
        {
            return MessageBox.Show(content, "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1);
        }

        public static DialogResult PopWarning(string content)
        {
            return MessageBox.Show(content, "警告", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
        }

        public static DialogResult PopError(string content)
        {
            return MessageBox.Show(content, "错误", MessageBoxButtons.OK, MessageBoxIcon.Hand, MessageBoxDefaultButton.Button1);
        }

        public static DialogResult PopQuestion(string content)
        {
            return MessageBox.Show(content, "询问", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
        }
    }
}
